import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import java.io.*;
import java.nio.channels.AsynchronousSocketChannel;

public class SpaceWar extends JPanel implements ActionListener {
	// This auto generated, I dont care :D
	private static final long serialVersionUID = 1L;

	private SpaceShip Player;

	public static int ScreenWidth;
	public static int ScreenHeight;

	private int Score;
	private int Life;

	private boolean HaveAlienShip = false;
	private boolean HaveRogueShip = false;

	private SavedScore[] highScoreHolder = new SavedScore[10];

	private int CurrentLevel;

	// Hold all object in this
	private ArrayList<Asteroid> AsteroidList = new ArrayList<Asteroid>();

	// Hold all alien ships
	private ArrayList<AlienShip> AlienList = new ArrayList<AlienShip>();

	// Hold all rogue ships
	private ArrayList<RogueSpaceShip> RogueList = new ArrayList<RogueSpaceShip>();

	private int FPS = 10;
	protected Timer timer = new Timer(this.FPS, this);
	private static boolean isPause;
	// Option the game
	static boolean gravitational = false;
	private static boolean grvVisible = false;
	private static boolean unLimitedLife = false;
	private static int NumerAsteroid;
	private static int StartLevel;

	private boolean getoutofGravitional;
	// Dialog
	Option op;
	PauseDialog pausdlg;

	public SpaceWar(int width, int heigh) {

		// Start timer
		this.timer.start();
		addKeyListener(new TAdapter());
		setFocusable(true);

		// Set screen with & high
		ScreenWidth = width;
		ScreenHeight = heigh;

		// Set new score
		Score = 0;
		Life = 3;
		CurrentLevel = 0;

		isPause = false;

		startLevel(CurrentLevel);
	}

	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		super.paint(g);
		Graphics2D g2d = (Graphics2D) g;
		Font font = new Font("Verdana", Font.BOLD, 16);
		g2d.setFont(font);
		setBackground(Color.black);
		g2d.setColor(Color.white);
		if (CurrentLevel == 0) {
			g2d.drawString("Press P to pause", 200, 140);
			g2d.drawString("Press ESC for Option menu", 200, 180);
			g2d.drawString("Max level is 5", 200, 220);
		} else {
			// Some text

			g2d.drawString("Score: " + Score, 400, 20);
			g2d.drawString("Life: " + Life, 200, 20);
			g2d.drawString("Level: " + CurrentLevel, 100, 20);
			// Draw all object here

			// gravitational
			if (gravitational && grvVisible) {
				g2d.drawOval(275, 175, 50, 50);
			}
			// Rener Astoroids
			for (int i = 0; i < AsteroidList.size(); i++) {
				g2d.draw(AsteroidList.get(i).getShape());
			}

			// Render player + bullets
			if(Player.isInvisible()){
				g2d.setColor(Color.cyan);
				g2d.draw(Player.getShape());
				g2d.setColor(Color.white);
			}
			else{
				g2d.draw(Player.getShape());
			}
			
			for (int j = 0; j < Player.getBulletList().size(); j++) {
				try {
					g2d.draw(Player.getBulletList().get(j).getShape());
				} catch (NullPointerException e) {
					// TODO: handle exception
				}
			}
			// Render alienships
			for (int i = 0; i < AlienList.size(); i++) {
				AlienShip alien = AlienList.get(i);
				g2d.draw(alien.getShape());
				for (int j = 0; j < alien.getBulletList().size(); j++) {
					try {
						g2d.draw(alien.getBulletList().get(j).getShape());
					} catch (NullPointerException e) {

					}
				}
			}

			// Render roguespaceships
			g2d.setColor(Color.green);
			for (int i = 0; i < RogueList.size(); i++) {
				RogueSpaceShip rogue = RogueList.get(i);
				g2d.draw(rogue.getShape());
				for (int j = 0; j < rogue.getBulletList().size(); j++) {

					try {
						g2d.draw(rogue.getBulletList().get(j).getShape());
					} catch (NullPointerException e) {

					}
				}
			}
		}

	}

	// This is main game loop

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		// System.out.println("Game looping...");
		if (isPause == false) {
			//
			if (CurrentLevel != 0 && AsteroidList.isEmpty()
					&& AlienList.isEmpty() && RogueList.isEmpty()) {
				Score += 100 * CurrentLevel;
				if (CurrentLevel < 5)
					CurrentLevel++;
				NumerAsteroid += 2;
				startLevel(CurrentLevel);
			}
			// Random alien ship

			//if (!HaveAlienShip)
			{
				Random randomNumber = new Random();
				if (randomNumber.nextInt(1000) == randomNumber.nextInt(1000)) {
					HaveAlienShip = true;
					AlienShip alien5 = new AlienShip(randomNumber.nextInt(600),
							0, CurrentLevel * 0.2f,
							(randomNumber.nextInt(160) + 10) + 180
									* randomNumber.nextInt(2));
					AlienList.add(alien5);
				}

			}
			if (!HaveRogueShip) {
				Random randomNumber = new Random();
				if (randomNumber.nextInt(10000) == randomNumber.nextInt(10000)) {
					HaveRogueShip = true;
					RogueSpaceShip rogue = new RogueSpaceShip(
							randomNumber.nextInt(600), 0, CurrentLevel * 0.2f,
							(randomNumber.nextInt(160) + 10) + 180
									* randomNumber.nextInt(2));
					RogueList.add(rogue);
				}

			}

			// Update asteroid
			for (int i = 0; i < AsteroidList.size(); i++) {
				AsteroidList.get(i).update();
			}
			Player.update();

			for (int i = 0; i < AlienList.size(); i++) {
				AlienShip alien = AlienList.get(i);
				alien.update();

				alien.fire(Player.getPosX(), Player.getPosY());
			}

			for (int i = 0; i < RogueList.size(); i++) {
				RogueSpaceShip rogue = RogueList.get(i);
				rogue.update();

				rogue.fire(Player.getPosX(), Player.getPosY());
			}

			// Check collision between asteroid and player
			CheckColAsPlayer();

			CheckColAsAlienShips();

			CheckColAsRogueShips();

			CheckColAlienPlayer();

			CheckColRoguePlayer();
			
			if (gravitational && grvVisible) {
				//g2d.drawOval(275, 175, 50, 50);
				//todo
				if (!getoutofGravitional){
					if(distance(300, 200, Player.getPosX(), Player.getPosY()) > 25 ){
						getoutofGravitional=true;
					}
				}
				if (getoutofGravitional){
					if(distance(300, 200, Player.getPosX(), Player.getPosY()) < 25 ){
						decreaseLife();
						Player = new SpaceShip(300, 200, 0);
					}
				}
			}
			repaint();
		}
	}

	public void startLevel(int lv) {
		CurrentLevel = lv;
		// reset all list
		AsteroidList = new ArrayList<Asteroid>();
		AlienList = new ArrayList<AlienShip>();
		RogueList = new ArrayList<RogueSpaceShip>();
		Player = new SpaceShip(300, 200, 0);

		HaveAlienShip = false;
		HaveRogueShip = false;
		
		getoutofGravitional =false;

		if (CurrentLevel == 0) {
			HaveAlienShip = true;
			HaveRogueShip = true;
		}
		// Start level with only 3 asteroids
		for (int i = 0; i < NumerAsteroid; i++) {
			Random r = new Random();
			Asteroid test1 = new Asteroid(r.nextInt(600), 400, 3,
					CurrentLevel * 0.2f, r.nextInt(360));
			AsteroidList.add(test1);
		}

	}

	// Check collision Player and RogueShips
	public void CheckColRoguePlayer() {

		if (!Player.isInvisible()) {
			for (int i = 0; i < RogueList.size(); i++) {
				RogueSpaceShip alien = RogueList.get(i);
				// player bullet vs alien ship
				for (int j = 0; j < Player.getBulletList().size(); j++) {
					double dis = distance(Player.getBulletList().get(j)
							.getPosX(),
							Player.getBulletList().get(j).getPosY(),
							alien.getPosX(), alien.getPosY());
					if (dis < 15) {
						Player.getBulletList().remove(j);
						Score += 100;

						RogueList.remove(i);

					}
				}

				// Alien ship vs player
				double dist = distance(Player.getPosX(), Player.getPosY(),
						alien.getPosX(), alien.getPosY());
				if (dist < 15) {
					Player = new SpaceShip(300, 200, 0);
					decreaseLife();
					break;
				}

				// Alien bullet vs player
				for (int j = 0; j < alien.getBulletList().size(); j++) {
					double dis = distance(alien.getBulletList().get(j)
							.getPosX(), alien.getBulletList().get(j).getPosY(),
							Player.getPosX(), Player.getPosY());
					// player get hit by alien ship's bullet
					// System.out.println(dis);
					if (dis < 15) {
						Player = new SpaceShip(300, 200, 0);
						decreaseLife();
						break;
					}
				}
			}
		}
	}

	public void CheckColAlienPlayer() {

		if (!Player.isInvisible()) {
			for (int i = 0; i < AlienList.size(); i++) {
				AlienShip alien = AlienList.get(i);
				// player bullet vs alien ship
				for (int j = 0; j < Player.getBulletList().size(); j++) {
					double dis = distance(Player.getBulletList().get(j)
							.getPosX(),
							Player.getBulletList().get(j).getPosY(),
							alien.getPosX(), alien.getPosY());
					if (dis < 15) {
						Player.getBulletList().remove(j);
						Score += 100;
						alien.setHP(alien.getHP() - 1);
						if (alien.getHP() == 0) {
							AlienList.remove(i);
							break;
						}
					}
				}

				// Alien ship vs player
				double dist = distance(Player.getPosX(), Player.getPosY(),
						alien.getPosX(), alien.getPosY());
				if (dist < 15) {
					decreaseLife();
					Player = new SpaceShip(300, 200, 0);
					
					break;
				}

				// Alien bullet vs player
				for (int j = 0; j < alien.getBulletList().size(); j++) {
					double dis = distance(alien.getBulletList().get(j)
							.getPosX(), alien.getBulletList().get(j).getPosY(),
							Player.getPosX(), Player.getPosY());
					// player get hit by alien ship's bullet
					// System.out.println(dis);
					if (dis < 15) {
						decreaseLife();
						Player = new SpaceShip(300, 200, 0);
						
						break;
					}
				}
			}
		}
	}

	public void decreaseLife() {
		Life--;
		getoutofGravitional=false;
		PlaySound("sfx_explode2.wav");
		if (Life <= 0 && !unLimitedLife) {
			System.out.println("Game over!");
			isPause = true;
			CurrentLevel=0;
			new EndGameDlg();
		}
	}

	public void PlaySound(final String filetopay) {
		Runnable r2 = new Runnable() {
			public void run() {

				try {
					AudioInputStream audio = AudioSystem
							.getAudioInputStream(new File(filetopay));
					Clip clip = AudioSystem.getClip();
					clip.open(audio);
					clip.start();
				}

				catch (UnsupportedAudioFileException uae) {
					System.out.println(uae);
				} catch (IOException ioe) {
					System.out.println(ioe);
				} catch (LineUnavailableException lua) {
					System.out.println(lua);
				}
			}
		};
		Thread thr2 = new Thread(r2);
		thr2.start();
	}

	public void CheckColAsPlayer() {
		for (int i = 0; i < AsteroidList.size(); i++) {
			// check collison with space ship
			if (!Player.isInvisible()) {
				double dist = distance(Player.getPosX(), Player.getPosY(),
						AsteroidList.get(i).getPosX(), AsteroidList.get(i)
								.getPosY());
				if (dist < AsteroidList.get(i).getRad() + 10) {
					Player = new SpaceShip(300, 200, 0);
					decreaseLife();
					BreakUpAsteroid(AsteroidList.get(i));
					break;
				}
			}

			// check collion with bullet
			for (int j = 0; j < Player.getBulletList().size(); j++) {

				double dis = distance(Player.getBulletList().get(j).getPosX(),
						Player.getBulletList().get(j).getPosY(), AsteroidList
								.get(i).getPosX(), AsteroidList.get(i)
								.getPosY());
				if (dis < (AsteroidList.get(i).getRad() + 5)) {
					Player.getBulletList().get(j).setLongLife(-1);
					Score += 5;
					// hit asteroid
					BreakUpAsteroid(AsteroidList.get(i));
					break;
				}

			}

		}
	}

	public void BreakUpAsteroid(Asteroid as) {
		// hit small asteroid
		PlaySound("sfx_explode1.wav");
		if (as.getType() == 1) {
			AsteroidList.remove(as);
		} else
		// hit medium asteroid
		if (as.getType() == 2) {
			Asteroid test1 = new Asteroid(as.getPosX(), as.getPosY(), 1,
					as.getSpeed(), as.getAngle() + 0);
			AsteroidList.add(test1);

			Asteroid test2 = new Asteroid(as.getPosX(), as.getPosY(), 1,
					as.getSpeed(), as.getAngle() + 120);
			AsteroidList.add(test2);

			Asteroid test3 = new Asteroid(as.getPosX(), as.getPosY(), 1,
					as.getSpeed(), as.getAngle() + 240);
			AsteroidList.add(test3);

			AsteroidList.remove(as);
		} else
		// hit larasteroid
		if (as.getType() == 3) {
			Asteroid test1 = new Asteroid(as.getPosX(), as.getPosY(), 2,
					as.getSpeed(), as.getAngle() + 0);
			AsteroidList.add(test1);

			Asteroid test2 = new Asteroid(as.getPosX(), as.getPosY(), 2,
					as.getSpeed(), as.getAngle() + 120);
			AsteroidList.add(test2);

			Asteroid test3 = new Asteroid(as.getPosX(), as.getPosY(), 2,
					as.getSpeed(), as.getAngle() + 240);
			AsteroidList.add(test3);
			AsteroidList.remove(as);
		}
	}

	public void CheckColAsAlienShips() {
		for (int o = 0; o < AlienList.size(); o++) {
			AlienShip alien = AlienList.get(o);
			for (int i = 0; i < AsteroidList.size(); i++) {
				// check collison with space ship
				double dist = distance(alien.getPosX(), alien.getPosY(),
						AsteroidList.get(i).getPosX(), AsteroidList.get(i)
								.getPosY());
				if (dist < AsteroidList.get(i).getRad() + 10) {
					BreakUpAsteroid(AsteroidList.get(i));
					break;
				}

				// check collion with bullet
				for (int j = 0; j < alien.getBulletList().size(); j++) {

					double dis = distance(alien.getBulletList().get(j)
							.getPosX(), alien.getBulletList().get(j).getPosY(),
							AsteroidList.get(i).getPosX(), AsteroidList.get(i)
									.getPosY());
					if (dis < (AsteroidList.get(i).getRad() + 5)) {

						alien.getBulletList().get(j).setLongLife(-1);
						BreakUpAsteroid(AsteroidList.get(i));

						break;
					}
				}
			}
		}

	}

	public void CheckColAsRogueShips() {
		for (int o = 0; o < RogueList.size(); o++) {
			RogueSpaceShip alien = RogueList.get(o);
			for (int i = 0; i < AsteroidList.size(); i++) {
				// check collison with space ship
				double dist = distance(alien.getPosX(), alien.getPosY(),
						AsteroidList.get(i).getPosX(), AsteroidList.get(i)
								.getPosY());
				if (dist < AsteroidList.get(i).getRad() + 10) {
					BreakUpAsteroid(AsteroidList.get(i));
					break;
				}

				// check collion with bullet
				for (int j = 0; j < alien.getBulletList().size(); j++) {

					double dis = distance(alien.getBulletList().get(j)
							.getPosX(), alien.getBulletList().get(j).getPosY(),
							AsteroidList.get(i).getPosX(), AsteroidList.get(i)
									.getPosY());
					if (dis < (AsteroidList.get(i).getRad() + 5)) {

						alien.getBulletList().get(j).setLongLife(-1);
						BreakUpAsteroid(AsteroidList.get(i));

						break;
					}
				}
			}
		}

	}

	public double distance(int x1, int y1, int x2, int y2) {
		return Math.sqrt((y1 - y2) * (y1 - y2) + (x1 - x2) * (x1 - x2));
	}

	// keylistener here
	private class TAdapter extends KeyAdapter {

		public void keyPressed(KeyEvent e) {
			// System.out.println("Rote your ship");
			int key = e.getKeyCode();
			if (key == KeyEvent.VK_LEFT) {
				Player.setAngle(Player.getAngle() - 15);
			}

			if (key == KeyEvent.VK_RIGHT) {
				Player.setAngle(Player.getAngle() + 15);
			}

			if (key == KeyEvent.VK_UP) {
				Player.setSpeed(Player.getSpeed() + 0.2f);
			}

			if (key == KeyEvent.VK_DOWN) {
				Player.setSpeed(Player.getSpeed() - 0.2f);
			}

			if (e.getKeyCode() == 32) {
				Player.fire();

			}
			if (key == KeyEvent.VK_ESCAPE) {
				isPause = true;
				op = new Option();
			}

			if (key == KeyEvent.VK_P) {
				if (CurrentLevel != 0) {
					isPause = true;
					pausdlg = new PauseDialog();
				}

			}
			if (key == KeyEvent.VK_Q) {
				if (CurrentLevel != 0) {
					isPause = true;
					pausdlg = new PauseDialog();
				}

			}
		}

	}

	private void ReadHighScore() {
		try {
			// Open the file that is the first
			// command line parameter
			FileInputStream fstream = new FileInputStream("highscore.txt");
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			// Read File Line By Line
			for (int i = 0; i < 10; i++) {
				strLine = br.readLine();
				String tmp[] = strLine.split(" ");
				highScoreHolder[i] = new SavedScore(Integer.parseInt(tmp[0]),
						tmp[1]);
			}
			// Close the input stream
			in.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	private void writeHighScore() {
		try {
			// Create file
			FileWriter fstream = new FileWriter("highscore.txt");
			BufferedWriter out = new BufferedWriter(fstream);
			for (int i = 0; i < 10; i++) {
				out.write(highScoreHolder[i].score + " "
						+ highScoreHolder[i].name + "\n");

			}
			// Close the output stream
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	private class EndGameDlg extends JFrame {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		// Read highScore
		public EndGameDlg() {
			addWindowListener(new java.awt.event.WindowAdapter() {
				public void windowClosing(WindowEvent winEvt) {
					// Perhaps ask user if they want to save any unsaved files
					// first.
					setVisible(false);
					Life = 3;
					Score = 0;
					startLevel(0);
					isPause = false;

				}
			});
			setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
			setSize(200, 300);
			setLocationRelativeTo(null);
			setTitle("Game Over!");
			setResizable(false);
			getContentPane().setBackground(Color.white);
			setLayout(new FlowLayout());
			// Read high score file
			ReadHighScore();
			setVisible(false);
			// Update highscore
			if (highScoreHolder[9].score < Score) {
				String str = JOptionPane.showInputDialog(null,
						"You got high score!\nPlease enter your name : ",
						"Congratulation!", 1);
				
				if(str.isEmpty()) str="Noname";
				else
					System.out.println("Name: "+str);
				highScoreHolder[9].score = Score;
				highScoreHolder[9].name = str;
				// highScoreHolder.remove(0);
				// highScoreHolder.add(Score);
				// Collections.sort(highScoreHolder);
				// Collections.sort(highScoreHolder);
			}
			setVisible(true);
			sortSaveScore();
			// Rewrite highscore to file
			writeHighScore();

			String str = "High Score\n------------\n";
			for (int i = 0; i < 10; i++) {
				str += highScoreHolder[i].score + "\t"
						+ highScoreHolder[i].name + "\n";

			}
			Font font = new Font("Verdana", Font.BOLD, 12);
			JTextArea textArea = new JTextArea();
			textArea.setFont(font);
			textArea.setForeground(Color.BLUE);
			textArea.setEditable(false);
			textArea.setText(str);
			getContentPane().add(textArea);

			// Close the output stream

			JButton btnPlay = new JButton("Play Again");
			JButton btnQuit = new JButton("Exit Game");
			getContentPane().add(btnPlay);
			getContentPane().add(btnQuit);
			btnQuit.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					System.exit(0);
				}
			});

			btnPlay.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					setVisible(false);
					Life = 3;
					Score = 0;
					startLevel(0);
					isPause = false;
				}
			});
		}

	}

	private class PauseDialog extends JFrame {

		private JButton btnContinue;
		private JButton btnQuitGame;
		private JButton btnSaveGame;
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public PauseDialog() {
			setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
			setSize(100, 150);
			setLocationRelativeTo(null);
			setTitle("Pause");
			setResizable(false);
			setVisible(true);
			setLayout(new FlowLayout());
			
			addWindowListener(new java.awt.event.WindowAdapter() {
				public void windowClosing(WindowEvent winEvt) {
					// Perhaps ask user if they want to save any unsaved files
					// first.
					SpaceWar.isPause = false;
					setVisible(false);

				}
			});
			btnContinue = new JButton("Continue");
			getContentPane().add(btnContinue);
			btnContinue.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					SpaceWar.isPause = false;
					setVisible(false);
				}
			});

			btnSaveGame = new JButton("Save Game");
			getContentPane().add(btnSaveGame);
			btnSaveGame.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					System.out.println("Save the game!");
					final JFileChooser fc = new JFileChooser();
					int returnVal = fc.showSaveDialog(PauseDialog.this);
					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						System.out.println(file.toPath());
						FileWriter fw;

						try {
							fw = new FileWriter(file);
							BufferedWriter out = new BufferedWriter(fw);
							out.write("1\t" + CurrentLevel + "\n");
							out.write("2\t" + Life + "\n");
							out.write("3\t" + Score + "\n");
							if (gravitational)
								out.write("5\t" + "1\n");
							else
								out.write("5\t" + "0\n");
							if (grvVisible)
								out.write("6\t" + "1\n");
							else
								out.write("6\t" + "0\n");
							// next N line is asteroid
							out.write("7\t" + AsteroidList.size() + "\n");
							for (int i = 0; i < AsteroidList.size(); i++) {
								out.write("8\t" + AsteroidList.get(i).getPosX()
										+ "\t" + AsteroidList.get(i).getPosY()
										+ "\t" + AsteroidList.get(i).getType()
										+ "\t" + AsteroidList.get(i).getSpeed()
										+ "\t" + AsteroidList.get(i).getAngle()
										+ "\n");
							}
							//
							out.write("9\t" + AlienList.size() + "\n");
							for (int i = 0; i < AlienList.size(); i++) {
								out.write("10\t" + AlienList.get(i).getPosX()
										+ "\t" + AlienList.get(i).getPosY()
										+ "\t" + AlienList.get(i).getSpeed()
										+ "\t" + AlienList.get(i).getAngle()
										+ "\n");
							}

							out.write("11\t" + RogueList.size() + "\n");
							for (int i = 0; i < RogueList.size(); i++) {
								out.write("12\t" + RogueList.get(i).getPosX()
										+ "\t" + RogueList.get(i).getPosY()
										+ "\t" + RogueList.get(i).getSpeed()
										+ "\t" + RogueList.get(i).getAngle()
										+ "\n");
							}

							System.out.println("Saved!");
							out.close();
							// etc...
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
				}
			});

			btnQuitGame = new JButton("Quit game");
			getContentPane().add(btnQuitGame);
			btnQuitGame.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					int response = JOptionPane.showConfirmDialog(null,
							"Do you want to quit?", "Confirm",
							JOptionPane.YES_NO_OPTION,
							JOptionPane.QUESTION_MESSAGE);
					if (response == JOptionPane.NO_OPTION) {
						System.out.println("No button clicked");
					} else if (response == JOptionPane.YES_OPTION) {
						
						System.out.println("Yes button clicked");
						ReadHighScore();
						
						// Update highscore
						if (highScoreHolder[9].score < Score) {
							String str = JOptionPane.showInputDialog(null,
									"You got high score!\nPlease enter your name : ",
									"Congratulation!", 1);
							System.out.println(str);
							if(str.isEmpty()) str="NoName";
							highScoreHolder[9].score = Score;
							highScoreHolder[9].name = str;
							// highScoreHolder.remove(0);
							// highScoreHolder.add(Score);
							// Collections.sort(highScoreHolder);
							// Collections.sort(highScoreHolder);
						}						
						sortSaveScore();
						// Rewrite highscore to file
						writeHighScore();
						
						System.exit(0);
					} else if (response == JOptionPane.CLOSED_OPTION) {
						System.out.println("JOptionPane closed");
					}

				}
			});
		}

	}

	private class Option extends JFrame {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		JCheckBox haveGravity;
		JCheckBox GravityVisible;
		JCheckBox UnlimitedLife;
		JButton btnResetHihScore;
		JButton btnStartNew;
		JButton btnExit;
		JButton btnLoad;
		JTextField txtLevel;
		JLabel lblLevel;
		JTextField txtAsteroid;
		JLabel lblAsteroid;

		public Option() {

			addWindowListener(new java.awt.event.WindowAdapter() {
				public void windowClosing(WindowEvent winEvt) {
					// Perhaps ask user if they want to save any unsaved files
					// first.
					SpaceWar.isPause = false;
					setVisible(false);

				}
			});

			setSize(250, 300);
			setLocationRelativeTo(null);
			setTitle("Options");
			setResizable(false);
			setVisible(true);
			setLayout(new FlowLayout());

			// Have a gravitational object?
			haveGravity = new JCheckBox("Have a gravitational object?");
			add(haveGravity);
			haveGravity.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					if (haveGravity.isSelected()) {
						System.out.println("Checked!");
						GravityVisible.setVisible(true);
						validate();
					} else {
						System.out.println("UnChecked!");
						GravityVisible.setVisible(false);
						validate();
					}
				}
			});

			// Gravitational Object visible?
			GravityVisible = new JCheckBox("Gravitational Object visible?");
			add(GravityVisible);
			GravityVisible.setVisible(false);
			GravityVisible.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					if (GravityVisible.isSelected())
						System.out.println("Checked!");
					else
						System.out.println("UnChecked!");
				}
			});
			// Play with unlimited file?
			UnlimitedLife = new JCheckBox("Play with Unlimited lives?");
			add(UnlimitedLife);
			UnlimitedLife.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					if (UnlimitedLife.isSelected())
						System.out.println("Checked!");
					else
						System.out.println("UnChecked!");
				}
			});

			// Number of asteroid
			lblAsteroid = new JLabel("Number of Asteroid: ");
			add(lblAsteroid);
			txtAsteroid = new JTextField(8);
			txtAsteroid.setText("3");
			add(txtAsteroid);

			// choose level
			lblLevel = new JLabel("Start at Level: ");
			add(lblLevel);
			txtLevel = new JTextField(3);
			txtLevel.setText("1");
			add(txtLevel);

			// resetHighScore
			btnResetHihScore = new JButton("Reset HighScore");
			add(btnResetHihScore);
			btnResetHihScore.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					ReadHighScore();
					for (int i = 0; i < 10; i++) {
						highScoreHolder[i].score = 0;
						highScoreHolder[i].name = "Null";

					}
					writeHighScore();

				}
			});

			btnLoad = new JButton("Load Game");
			add(btnLoad);
			btnLoad.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					System.out.print("Loaded Game!\n");
					final JFileChooser fc = new JFileChooser();
					int returnVal = fc.showOpenDialog(Option.this);
					if (returnVal == JFileChooser.APPROVE_OPTION) {
						File file = fc.getSelectedFile();
						try {
							FileInputStream fstream = new FileInputStream(file);
							// Get the object of DataInputStream
							DataInputStream in = new DataInputStream(fstream);
							BufferedReader br = new BufferedReader(
									new InputStreamReader(in));
							String strLine;
							AsteroidList.clear();
							AlienList.clear();
							RogueList.clear();
							while ((strLine = br.readLine()) != null) {
								// Print the content on the console
								String tmp[] = strLine.split("\t");
								if (Integer.parseInt(tmp[0]) == 1) {
									CurrentLevel = Integer.parseInt(tmp[1]);
								}
								if (Integer.parseInt(tmp[0]) == 2) {
									Life = Integer.parseInt(tmp[1]);
								}
								if (Integer.parseInt(tmp[0]) == 3) {
									Score = Integer.parseInt(tmp[1]);
								}
								if (Integer.parseInt(tmp[0]) == 5) {
									if (Integer.parseInt(tmp[1]) == 1)
										gravitational = true;
									else
										gravitational = false;
								}
								if (Integer.parseInt(tmp[0]) == 6) {
									if (Integer.parseInt(tmp[1]) == 1)
										grvVisible = true;
									else
										grvVisible = false;
								}

								if (Integer.parseInt(tmp[0]) == 8) {

									Asteroid as = new Asteroid(Integer
											.parseInt(tmp[1]), Integer
											.parseInt(tmp[2]), Integer
											.parseInt(tmp[3]), Float
											.parseFloat(tmp[4]), Integer
											.parseInt(tmp[5]));
									AsteroidList.add(as);
								}

								if (Integer.parseInt(tmp[0]) == 10) {

									AlienShip as = new AlienShip(Integer
											.parseInt(tmp[1]), Integer
											.parseInt(tmp[2]), Float
											.parseFloat(tmp[3]), Integer
											.parseInt(tmp[4]));
									AlienList.add(as);
								}

								if (Integer.parseInt(tmp[0]) == 12) {

									RogueSpaceShip as = new RogueSpaceShip(
											Integer.parseInt(tmp[1]), Integer
													.parseInt(tmp[2]), Float
													.parseFloat(tmp[3]),
											Integer.parseInt(tmp[4]));
									RogueList.add(as);
								}
								in.close();
							}
						} catch (Exception fileException) {
							// TODO: handle exception
						}

					}
					isPause = false;
					setVisible(false);

				}
			});

			btnExit = new JButton("Cancel");
			add(btnExit);
			btnExit.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					setVisible(false);
					SpaceWar.isPause = false;
				}
			});

			btnStartNew = new JButton("Start New Game");
			add(btnStartNew);
			btnStartNew.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					// TODO Auto-generated method stub
					if (txtAsteroid.getText() != "") {

						SpaceWar.NumerAsteroid = Integer.parseInt(txtAsteroid
								.getText());
						SpaceWar.gravitational = haveGravity.isSelected();
						SpaceWar.grvVisible = GravityVisible.isSelected();
						Life = 3;
						Score = 0;
						SpaceWar.StartLevel = Integer.parseInt(txtLevel
								.getText());
						SpaceWar.unLimitedLife = UnlimitedLife.isSelected();
						SpaceWar.isPause = false;
						startLevel(SpaceWar.StartLevel);
						setVisible(false);
					}
				}
			});
		}

	}

	private class SavedScore {
		public String name;
		public int score;

		SavedScore(int sc, String nm) {
			name = nm;
			score = sc;
		}
	}

	public void sortSaveScore() {
		for (int i = 0; i < 9; i++)
			for (int j = i + 1; j < 10; j++) {
				if (highScoreHolder[i].score < highScoreHolder[j].score) {
					SavedScore t = highScoreHolder[j];
					highScoreHolder[j] = highScoreHolder[i];
					highScoreHolder[i] = t;
				}
			}
	}
}
